import * as fs from 'fs';
import { FrontendParser } from '../utils/FrontendParser';

/**
 * React组件重构工具
 */
export class ReactRefactor {
    
    /**
     * 将React Class组件转换为Hooks组件
     */
    async convertClassToHooks(filePath: string): Promise<{
        success: boolean;
        message: string;
        filesModified: string[];
        originalComponent: string;
        hooksComponent: string;
        appliedChanges: string[];
        errors: string[];
    }> {
        const result = {
            success: false,
            message: '',
            filesModified: [] as string[],
            originalComponent: '',
            hooksComponent: '',
            appliedChanges: [] as string[],
            errors: [] as string[]
        };

        try {
            const content = await fs.promises.readFile(filePath, 'utf-8');
            result.originalComponent = this.extractComponentName(content);

            if (!FrontendParser.isReactClassComponent(content)) {
                result.message = '这不是一个React Class组件，无法转换';
                return result;
            }

            // 分析Hooks转换机会
            const hooksOpportunities = FrontendParser.analyzeHooksOpportunities(content);
            const methods = FrontendParser.extractReactClassMethods(content);

            if (hooksOpportunities.length === 0) {
                result.message = '该组件已经是现代化的，无需转换为Hooks';
                return result;
            }

            // 执行转换
            const convertedContent = await this.performClassToHooksConversion(content, methods, hooksOpportunities);
            
            // 备份原文件
            const backupPath = filePath.replace('.jsx', '.class-backup.jsx').replace('.js', '.class-backup.js');
            await fs.promises.writeFile(backupPath, content);

            // 写入转换后的内容
            await fs.promises.writeFile(filePath, convertedContent);

            result.success = true;
            result.message = `成功将Class组件转换为Hooks组件，应用了${hooksOpportunities.length}个优化`;
            result.filesModified = [filePath];
            result.hooksComponent = this.extractComponentName(convertedContent);
            result.appliedChanges = hooksOpportunities.map(op => `${op.type}: ${op.suggestion}`);

        } catch (error) {
            result.errors.push(`转换失败: ${error}`);
            result.message = `转换失败: ${error}`;
        }

        return result;
    }

    /**
     * 提取自定义Hook
     */
    async extractCustomHook(filePath: string): Promise<{
        success: boolean;
        message: string;
        filesModified: string[];
        extractedHooks: Array<{
            name: string;
            filePath: string;
            description: string;
        }>;
        appliedChanges: string[];
        errors: string[];
    }> {
        const result = {
            success: false,
            message: '',
            filesModified: [] as string[],
            extractedHooks: [] as Array<{
                name: string;
                filePath: string;
                description: string;
            }>,
            appliedChanges: [] as string[],
            errors: [] as string[]
        };

        try {
            const content = await fs.promises.readFile(filePath, 'utf-8');
            const customHookSuggestions = FrontendParser.suggestCustomHooks(content);

            if (customHookSuggestions.length === 0) {
                result.message = '未发现可以提取的自定义Hook模式';
                return result;
            }

            const extractedHooks: Array<{
                name: string;
                filePath: string;
                description: string;
            }> = [];

            for (const suggestion of customHookSuggestions) {
                const hookContent = this.generateCustomHook(suggestion);
                const hookFilePath = this.generateHookFilePath(filePath, suggestion.suggestedHookName);
                
                await fs.promises.writeFile(hookFilePath, hookContent);
                
                extractedHooks.push({
                    name: suggestion.suggestedHookName,
                    filePath: hookFilePath,
                    description: suggestion.description
                });

                result.appliedChanges.push(`提取自定义Hook: ${suggestion.suggestedHookName}`);
            }

            // 更新原组件，使用新的自定义Hook
            const updatedContent = this.updateComponentToUseCustomHooks(content, customHookSuggestions);
            await fs.promises.writeFile(filePath, updatedContent);

            result.success = true;
            result.message = `成功提取了${extractedHooks.length}个自定义Hook`;
            result.filesModified = [filePath, ...extractedHooks.map(h => h.filePath)];
            result.extractedHooks = extractedHooks;

        } catch (error) {
            result.errors.push(`提取自定义Hook失败: ${error}`);
            result.message = `提取失败: ${error}`;
        }

        return result;
    }

    /**
     * 优化React组件性能
     */
    async optimizeReactPerformance(filePath: string): Promise<{
        success: boolean;
        message: string;
        filesModified: string[];
        optimizations: Array<{
            type: string;
            description: string;
            applied: boolean;
        }>;
        appliedChanges: string[];
        errors: string[];
    }> {
        const result = {
            success: false,
            message: '',
            filesModified: [] as string[],
            optimizations: [] as Array<{
                type: string;
                description: string;
                applied: boolean;
            }>,
            appliedChanges: [] as string[],
            errors: [] as string[]
        };

        try {
            const content = await fs.promises.readFile(filePath, 'utf-8');
            let optimizedContent = content;
            const optimizations: Array<{
                type: string;
                description: string;
                applied: boolean;
            }> = [];

            // 1. 添加React.memo包装
            if (!content.includes('React.memo') && !content.includes('memo(')) {
                optimizedContent = this.addReactMemo(optimizedContent);
                optimizations.push({
                    type: 'React.memo',
                    description: '添加React.memo防止不必要的重渲染',
                    applied: true
                });
                result.appliedChanges.push('添加React.memo优化');
            }

            // 2. 优化事件处理函数
            const eventHandlerOptimization = this.optimizeEventHandlers(optimizedContent);
            if (eventHandlerOptimization.modified) {
                optimizedContent = eventHandlerOptimization.content;
                optimizations.push({
                    type: 'useCallback',
                    description: '使用useCallback优化事件处理函数',
                    applied: true
                });
                result.appliedChanges.push('优化事件处理函数');
            }

            // 3. 优化昂贵计算
            const memoOptimization = this.addUseMemoForExpensiveCalculations(optimizedContent);
            if (memoOptimization.modified) {
                optimizedContent = memoOptimization.content;
                optimizations.push({
                    type: 'useMemo',
                    description: '使用useMemo缓存昂贵计算',
                    applied: true
                });
                result.appliedChanges.push('缓存昂贵计算');
            }

            // 4. 检查是否需要懒加载
            if (content.includes('import') && !content.includes('lazy(')) {
                const lazyImportSuggestion = this.suggestLazyLoading(content);
                if (lazyImportSuggestion) {
                    optimizations.push({
                        type: 'lazy-loading',
                        description: '建议使用React.lazy进行代码分割',
                        applied: false
                    });
                }
            }

            if (optimizedContent !== content) {
                await fs.promises.writeFile(filePath, optimizedContent);
                result.filesModified = [filePath];
            }

            result.success = true;
            result.message = `应用了${result.appliedChanges.length}个性能优化`;
            result.optimizations = optimizations;

        } catch (error) {
            result.errors.push(`性能优化失败: ${error}`);
            result.message = `优化失败: ${error}`;
        }

        return result;
    }

    /**
     * 将Class组件转换为Hooks的核心逻辑
     */
    private async performClassToHooksConversion(
        content: string, 
        methods: Array<{name: string; startLine: number; endLine: number; isLifecycle: boolean; content: string}>,
        opportunities: Array<{type: string; suggestion: string; line: number; replacement: string}>
    ): Promise<string> {
        let converted = content;
        
        // 1. 提取imports（确保包含React Hooks）
        const imports = this.extractAndUpdateImports(converted);
        
        // 2. 提取组件名
        const componentName = this.extractComponentName(converted);
        
        // 3. 转换state为useState
        converted = this.convertStateToUseState(converted);
        
        // 4. 转换生命周期方法为useEffect
        converted = this.convertLifecycleToUseEffect(converted, methods);
        
        // 5. 转换class方法为常规函数
        converted = this.convertClassMethodsToFunctions(converted, methods);
        
        // 6. 构建函数组件结构
        const functionComponent = this.buildFunctionComponent(componentName, converted, imports);
        
        return functionComponent;
    }

    private extractComponentName(content: string): string {
        const classMatch = content.match(/class\s+(\w+)\s+extends/);
        if (classMatch) {
            return classMatch[1];
        }
        
        const exportMatch = content.match(/export\s+default\s+(\w+)/);
        if (exportMatch) {
            return exportMatch[1];
        }
        
        return 'Component';
    }

    private extractAndUpdateImports(content: string): string {
        const reactImport = content.match(/import\s+React.*from\s+['"]react['"];?/);
        if (reactImport) {
            // 确保包含必要的Hooks
            const hasUseState = reactImport[0].includes('useState');
            const hasUseEffect = reactImport[0].includes('useEffect');
            
            if (!hasUseState || !hasUseEffect) {
                return `import React, { useState, useEffect, useCallback, useMemo } from 'react';`;
            }
        }
        
        return `import React, { useState, useEffect, useCallback, useMemo } from 'react';`;
    }

    private convertStateToUseState(content: string): string {
        // 查找state初始化
        const stateMatch = content.match(/state\s*=\s*\{([\s\S]*?)\};?/);
        if (stateMatch) {
            const stateContent = stateMatch[1];
            const stateLines = stateContent.split('\n').map(line => line.trim()).filter(line => line);
            
            let useStateDeclarations = '';
            for (const line of stateLines) {
                const propMatch = line.match(/(\w+):\s*(.+),?/);
                if (propMatch) {
                    const [, propName, initialValue] = propMatch;
                    useStateDeclarations += `  const [${propName}, set${this.capitalize(propName)}] = useState(${initialValue.replace(/,$/, '')});\n`;
                }
            }
            
            return content.replace(/state\s*=\s*\{[\s\S]*?\};?/, useStateDeclarations);
        }
        
        return content;
    }

    private convertLifecycleToUseEffect(content: string, methods: Array<{name: string; isLifecycle: boolean; content: string}>): string {
        let converted = content;
        
        for (const method of methods) {
            if (method.isLifecycle) {
                switch (method.name) {
                    case 'componentDidMount':
                        const mountContent = this.extractMethodBody(method.content);
                        converted = converted.replace(method.content, `  useEffect(() => {\n${mountContent}\n  }, []);\n`);
                        break;
                        
                    case 'componentDidUpdate':
                        const updateContent = this.extractMethodBody(method.content);
                        converted = converted.replace(method.content, `  useEffect(() => {\n${updateContent}\n  });\n`);
                        break;
                        
                    case 'componentWillUnmount':
                        const unmountContent = this.extractMethodBody(method.content);
                        converted = converted.replace(method.content, `  useEffect(() => {\n    return () => {\n${unmountContent}\n    };\n  }, []);\n`);
                        break;
                }
            }
        }
        
        return converted;
    }

    private convertClassMethodsToFunctions(content: string, methods: Array<{name: string; isLifecycle: boolean; content: string}>): string {
        let converted = content;
        
        for (const method of methods) {
            if (!method.isLifecycle && method.name !== 'render') {
                // 转换class方法为useCallback包装的函数
                const methodBody = this.extractMethodBody(method.content);
                const callbackFunction = `  const ${method.name} = useCallback(${methodBody}, []);\n`;
                converted = converted.replace(method.content, callbackFunction);
            }
        }
        
        return converted;
    }

    private buildFunctionComponent(componentName: string, convertedContent: string, imports: string): string {
        // 提取render方法的内容
        const renderMatch = convertedContent.match(/render\s*\(\s*\)\s*\{([\s\S]*)\}/);
        let renderContent = 'return <div>Component</div>;';
        
        if (renderMatch) {
            renderContent = renderMatch[1].trim();
            if (!renderContent.startsWith('return')) {
                renderContent = `return (${renderContent});`;
            }
        }
        
        // 提取所有useState、useEffect等声明
        const hookDeclarations = this.extractHookDeclarations(convertedContent);
        
        return `${imports}

const ${componentName} = () => {
${hookDeclarations}

  ${renderContent}
};

export default ${componentName};
`;
    }

    private extractMethodBody(methodContent: string): string {
        const match = methodContent.match(/\{([\s\S]*)\}/);
        return match ? match[1].trim() : '';
    }

    private extractHookDeclarations(content: string): string {
        const hookPatterns = [
            /const\s+\[.*?\]\s*=\s*useState\(.*?\);/g,
            /useEffect\([\s\S]*?\);/g,
            /const\s+\w+\s*=\s*useCallback\([\s\S]*?\);/g,
            /const\s+\w+\s*=\s*useMemo\([\s\S]*?\);/g
        ];
        
        let declarations = '';
        for (const pattern of hookPatterns) {
            const matches = content.match(pattern);
            if (matches) {
                declarations += matches.map(match => `  ${match}`).join('\n') + '\n';
            }
        }
        
        return declarations;
    }

    private generateCustomHook(suggestion: {name: string; description: string; logic: string[]; suggestedHookName: string}): string {
        return `import { useState, useEffect, useCallback } from 'react';

/**
 * ${suggestion.description}
 */
export const ${suggestion.suggestedHookName} = () => {
  // TODO: 实现${suggestion.name}的逻辑
  ${suggestion.logic.map(logic => `  // ${logic}`).join('\n')}
  
  return {
    // 返回需要的状态和方法
  };
};
`;
    }

    private generateHookFilePath(originalPath: string, hookName: string): string {
        const dir = originalPath.substring(0, originalPath.lastIndexOf('/'));
        const fileName = hookName.replace(/([A-Z])/g, '-$1').toLowerCase();
        return `${dir}/hooks/${fileName}.js`;
    }

    private updateComponentToUseCustomHooks(content: string, suggestions: Array<{suggestedHookName: string}>): string {
        let updated = content;
        
        // 添加自定义Hook的import
        const imports = suggestions.map(s => `import { ${s.suggestedHookName} } from './hooks/${s.suggestedHookName.replace(/([A-Z])/g, '-$1').toLowerCase()}';`).join('\n');
        
        // 在React import后添加自定义Hook imports
        updated = updated.replace(/(import React.*?;)/, `$1\n${imports}`);
        
        return updated;
    }

    private addReactMemo(content: string): string {
        // 查找默认导出的组件
        const exportMatch = content.match(/export\s+default\s+(\w+);?/);
        if (exportMatch) {
            const componentName = exportMatch[1];
            return content.replace(
                exportMatch[0],
                `export default React.memo(${componentName});`
            );
        }
        return content;
    }

    private optimizeEventHandlers(content: string): {modified: boolean; content: string} {
        let modified = false;
        let optimized = content;
        
        // 查找内联事件处理函数
        const inlineHandlerPattern = /(\w+)=\{([^}]*=>[^}]*)\}/g;
        const matches = content.match(inlineHandlerPattern);
        
        if (matches) {
            // 为每个内联处理函数创建useCallback版本
            for (const match of matches) {
                const handlerMatch = match.match(/(\w+)=\{([^}]*=>[^}]*)\}/);
                if (handlerMatch) {
                    const [, propName, handler] = handlerMatch;
                    const callbackName = `handle${this.capitalize(propName.replace('on', ''))}`;
                    
                    // 在组件顶部添加useCallback
                    const callbackDeclaration = `  const ${callbackName} = useCallback(${handler}, []);\n`;
                    optimized = optimized.replace(
                        /(const \w+ = .*?\) => \{)/,
                        `$1\n${callbackDeclaration}`
                    );
                    
                    // 替换内联处理函数
                    optimized = optimized.replace(match, `${propName}={${callbackName}}`);
                    modified = true;
                }
            }
        }
        
        return { modified, content: optimized };
    }

    private addUseMemoForExpensiveCalculations(content: string): {modified: boolean; content: string} {
        let modified = false;
        let optimized = content;
        
        // 查找可能昂贵的计算模式
        const expensivePatterns = [
            /\.filter\(.*?\)\.map\(.*?\)/g,
            /\.sort\(.*?\)/g,
            /\.reduce\(.*?\)/g
        ];
        
        for (const pattern of expensivePatterns) {
            const matches = content.match(pattern);
            if (matches) {
                for (const match of matches) {
                    // 将昂贵计算包装在useMemo中
                    const memoized = `useMemo(() => ${match}, [/* dependencies */])`;
                    optimized = optimized.replace(match, memoized);
                    modified = true;
                }
            }
        }
        
        return { modified, content: optimized };
    }

    private suggestLazyLoading(content: string): boolean {
        // 检查是否有大量的import或复杂组件
        const importCount = (content.match(/import.*from/g) || []).length;
        const componentSize = content.length;
        
        return importCount > 10 || componentSize > 5000;
    }

    private capitalize(str: string): string {
        return str.charAt(0).toUpperCase() + str.slice(1);
    }
}